package com.daxue.eurekaclientuserservice.jarload.adaptor;

import com.daxue.eurekaclientuserservice.jarload.adaptor.manager.AdaptorResourceManager;
import com.daxue.eurekaclientuserservice.jarload.adaptor.model.AdaptorResourceConfig;
import com.daxue.eurekaclientuserservice.jarload.adaptor.model.AdaptorResourceModel;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author daxue0929
 * @date 2023/2/8
 */

@Slf4j
@Component
public class IdentityAdaptorPool {

    private Map<String, BaseIdentityAdaptor> adaptorCachePool = new ConcurrentHashMap<>();

    private final Map<String, String> adaptorVersionMap = new ConcurrentHashMap<>();

    final AdaptorResourceManager adaptorResourceManager;
    final AdaptorConfiguration adaptorConfiguration;

    public IdentityAdaptorPool(AdaptorResourceManager adaptorResourceManager,
                               AdaptorConfiguration adaptorConfiguration) {
        this.adaptorResourceManager = adaptorResourceManager;
        this.adaptorConfiguration = adaptorConfiguration;
    }

    public BaseIdentityAdaptor loadAdaptorInstance(String adaptorId) throws Exception {
        AdaptorResourceModel adaptorResourceModel = adaptorResourceManager.getById(adaptorId);
        String currentVersion = adaptorResourceModel.getVersion();
        //加载过且版本没有变化，直接返回
        if (adaptorVersionMap.containsKey(adaptorId) &&
            currentVersion.equals(adaptorVersionMap.get(adaptorId))) {
            return adaptorCachePool.get(adaptorId);
        }else {
            synchronized (this) {
                //adaptor version版本变更，重新加载并清除旧版本的cache
                String oldVersion = adaptorVersionMap.get(adaptorId);
                if (!currentVersion.equals(oldVersion)) {
                    //如果存在旧版本,则清除旧版本
                    if (oldVersion != null) {
                        adaptorCachePool.remove(adaptorId);
                        log.debug("remove old version adaptor:{}-{}", adaptorId, oldVersion);
                    }
                    adaptorVersionMap.put(adaptorId, currentVersion); //更新缓存中的版本
                }
                BaseIdentityAdaptor baseIdentityAdaptor = loadInstance(adaptorId);
                adaptorCachePool.put(adaptorId, baseIdentityAdaptor);
                return baseIdentityAdaptor;
            }
        }
    }

    private BaseIdentityAdaptor loadInstance(String adaptorId) throws Exception {
        AdaptorResourceModel adaptorResourceModel = adaptorResourceManager.getById(adaptorId);
        AdaptorResourceConfig resourceConfig = adaptorResourceModel.getResourceConfig();

        // 拼接完整的URI网络资源地址
        URL resourceUrl = new URL(adaptorConfiguration.getAdaptorStorageUrl() +
            resourceConfig.getResourceUrl());
        String resourceType = resourceConfig.getResourceType();

        try (URLClassLoader urlClassLoader = new URLClassLoader(new URL[]{resourceUrl})) {
            Class<? extends BaseIdentityAdaptor> clazz =
                (Class<? extends BaseIdentityAdaptor>) urlClassLoader.loadClass(resourceType);
            Constructor<? extends BaseIdentityAdaptor> constructor = clazz.getDeclaredConstructor();
            BaseIdentityAdaptor instance = constructor.newInstance();
            log.debug("load new instance for adaptor:{}", adaptorId);
            return instance;
        } catch (IOException | ClassNotFoundException | NoSuchMethodException |
            InstantiationException | IllegalAccessException | InvocationTargetException e) {
            e.printStackTrace();
            log.debug("load new instance for adaptor: {}, exception:{}", adaptorId, e.getMessage());
            throw new Exception(e.getMessage());
        }
    }


}
